/*
 * Copyright 2010 Joshua Smith and Nelson Llewellyn
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package norse.util;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import norse.msg.NoRSeScanRequest;
import norse.msg.NoRSeScanRequestResponse;
import norse.msg.NoRSeScanResults;
import norse.plugins.MessageClassProviderIF;
import norse.plugins.nmap.NmapPackageProvider;

/**
 * Utility class that creates and initializes a JAXB Context.
 */
public final class JaxbContextGenerator
{
    /** Plugin Package Providers to query */
    private static final MessageClassProviderIF[] pluginProviders =
    {
        new NmapPackageProvider()
    };

    /** Classes to statically add to the class list */
    private static final Class [] staticClasses
            = { NoRSeScanRequest.class, NoRSeScanResults.class,
            NoRSeScanRequestResponse.class };

    /**
     * The colon-seperated list of class containing root messages.
     */
    private static Class [] classArray = buildMessageClassesArray();

    /**
     * Get a new JAXB Context that has been initialized with the proper
     * packages.
     *
     * @return the initialized JAXB Context
     *
     * @throws JAXBException if there is an error during JAXB Context creation
     */
    /*
     * Default access is intentional--this method should only be used by the
     * MessageMarshaller and MessageUnmarshaller classes.
     */
    static JAXBContext getContext() throws JAXBException
    {
        return JAXBContext.newInstance(classArray);
    }

    /**
     * Build the array of classes containing root messages.
     */
    private static Class[] buildMessageClassesArray()
    {
        int numArrays = pluginProviders.length;

        Class[][] messageClasses2dArray = new Class[numArrays][];
        int totalLength = 0;
        int currIndex = 0;
        
        for (MessageClassProviderIF currProvider : pluginProviders)
        {
            Class [] currClassArray = currProvider.getClasses();

            messageClasses2dArray[currIndex] = currClassArray;

            if (currClassArray != null)
            {
                totalLength += currClassArray.length;
            }

            ++currIndex;
        }

        Class[] finalClassArray = new Class[totalLength + staticClasses.length];
        currIndex = 0;

        for (Class[] currClassArray : messageClasses2dArray)
        {
            if (currClassArray != null)
            {
                for (Class currClass : currClassArray)
                {
                    finalClassArray[currIndex] = currClass;
                    ++currIndex;
                }
            }
        }

        for (Class currClass : staticClasses)
        {
            finalClassArray[currIndex] = currClass;
            ++currIndex;
        }

        return finalClassArray;
    }

    /**
     * Private constructor to prevent instantiation.
     */
    private JaxbContextGenerator()
    {
    }
}
